#pragma once
#include <functional>
#include <memory>


#include "noncopyable.h"
#include "timestamp.h"

class EventLoop;

/**
 * channel 理解为通道，  封装了sockfd和其感兴趣的event，如EPOLLIN、EPOLLOUT事件
    还绑定了poller返回具体事件
 */

class Channel : noncopyable{
public:
    using EventCallBack = std::function<void()>;
    using ReadEventCallBack = std::function<void(TimeStamp)>;

    Channel(EventLoop* loop, int fd);
    ~Channel();
    // fd 得到poller通知以后  处理事件
    void handlerEvent(TimeStamp receiveTime);
    
    // 设置回调函数对象
    void setReadCallBack(ReadEventCallBack cb){
        readCallBack_ = std::move(cb);
    }

    void setWriteCallBack(EventCallBack cb){
        writeCallBack_ = std::move(cb);
    }

    void setCloseCallBack(EventCallBack cb){
        closeCallBack_ = std::move(cb);
    }

    void setErrorCallBack(EventCallBack cb){
        errorCallBack_ = std::move(cb);
    }

    // 防止当channel被手动remove掉时， channel还在执行回调操作
    void tie(const std::shared_ptr<void>& );

    int fd() const {return fd_;};
    int events() const {return events_;};
    void set_revent(int revents) {revents_ = revents;}
    
    

    // 设置fd对象的事件
    void enableReading(){events_ |= kReadEvent; update();}
    void disableReading() {events_ &= ~kReadEvent;  update();}
    void enableWriteing(){events_ |= kWriteEvent;  update();}
    void disableWriteing() {events_ &= ~kWriteEvent;  update();}
    void disableAll() { events_ = kNoneEvent;  update();}

    bool isReading() const {return revents_ & kReadEvent;}
    bool isWriting() const {return revents_ & kWriteEvent;}
    bool isNoneEvent() const {return events_ == kNoneEvent;}

    int index() {return index_;}
    void set_index(int idx) {index_ = idx;}

    // one loop per thread
    EventLoop* ownerLoop() {return loop_;}
    void remove();
    

private:
    // 同时也会把自己注册到EventLoop里面
    void update();
    void handleEventWithGuard(TimeStamp receiveTime);

    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop* loop_;
    const int fd_;
    // 感兴趣的事件
    int events_;
    // 实际发生的事件
    int revents_;
    // channel 的状态
    int index_;

    std::weak_ptr<void> tie_;
    bool tied_;

    // 因为channel 里面能够获知fd最终的具体事件的revent
    ReadEventCallBack readCallBack_;
    EventCallBack writeCallBack_;
    EventCallBack closeCallBack_;
    EventCallBack errorCallBack_;
};